using System;
using System.Collections.Generic;
using SkaldRogueLike.Main.Common;
using SkaldRogueLike.Main.Constants;

namespace SkaldRogueLike.Main.DungeonGenerating.DirectionProcessing
{
    public class DirectionProcessor
    {
        public bool HasDirs { get { return _dirs.Count > 0; } }
        public int ChangeDirMod { get; set; }
        private Dir _previous;
        private List<Dir> _dirs;

        public DirectionProcessor(int changeDirMod)
        {
            ChangeDirMod = changeDirMod;
            RestoreDirs();
            _previous = _dirs[StaticRandom.Next(_dirs.Count)];
        }

        public void RestoreDirs()
        {
            _dirs = new List<Dir> { Dir.North, Dir.East, Dir.South, Dir.West };
        }

        public Dir GetNextDirection(Dir previous)
        {
            _previous = previous;
            return GetNextDirection();
        }

        public Dir GetNextDirection()
        {
            if (!HasDirs)
                throw new InvalidOperationException("No dirs left.");
            if (MustChangeDir() || !_dirs.Contains(_previous))
            {
                Dir current;
                do
                {
                    current = _dirs[StaticRandom.Next(_dirs.Count)];
                } while (_previous == current);
                _previous = current;
            }
            _dirs.Remove(_previous);
            return _previous;
        }

        public bool MustChangeDir()
        {
            switch (ChangeDirMod)
            {
                case 0:
                    return false;
                case 100:
                    return true;
                default:
                    return ChangeDirMod > StaticRandom.Next(100);
            }
        }

        public static Dir GetOppositeDir(Dir dir)
        {
            switch (dir)
            {
                case Dir.North:
                    return Dir.South;
                case Dir.South:
                    return Dir.North;
                case Dir.West:
                    return Dir.East;
                case Dir.East:
                    return Dir.West;
                default:
                    throw new ArgumentException("Invalid direction provided.");
            }
        }
    }
}